/* 
* Purpose: External interrupt driver/interface
*
* Author: Allen Lin
*
* Date: 2008/05/28
*
* Copyright Generalplus Corp. ALL RIGHTS RESERVED.
*
* Version : 1.00
*/
#include "drv_l1_ext_int.h"

//=== This is for code configuration DON'T REMOVE or MODIFY it ===//
#if (defined _DRV_L1_EXT_INT) && (_DRV_L1_EXT_INT == 1) //

//================================================================//
typedef struct
{	// Offset
	volatile INT32U EXTERNAL_INT_KECON; // 0x0000
} EXTERNAL_INT_SFR;

/*****************************************************/
void (*exta_callback) (void);
void (*extb_callback) (void);
void (*extc_callback) (void);

void	extab_int_isr(void);

void (*key_change_callback) (void);
/*****************************************************
* get_EXTERNAL_INT_Reg_Base:
*
*****************************************************/
static EXTERNAL_INT_SFR *get_EXTERNAL_INT_Reg_Base(void)
{
	return (EXTERNAL_INT_SFR *) P_EXTERNAL_INT_BASE;
}

void ext_int_init(int enable)
{
	EXTERNAL_INT_SFR	*pExternal_INT_Reg;

	pExternal_INT_Reg = get_EXTERNAL_INT_Reg_Base();

	extab_int_clr(EXTA);
	extab_int_clr(EXTB);
	extab_int_clr(EXTC);
	pExternal_INT_Reg->EXTERNAL_INT_KECON &= ~0x1FF;
	extab_user_isr_clr(EXTA);
	extab_user_isr_clr(EXTB);
	extab_user_isr_clr(EXTC);
	if(enable & 0x1)
	{
		vic_irq_register(VIC_EXT_A, extab_int_isr);
		vic_irq_enable(VIC_EXT_A);
	}

	if(enable & 0x2)
	{
		vic_irq_register(VIC_EXT_B, extab_int_isr);
		vic_irq_enable(VIC_EXT_B);
	}

	if(enable & 0x4)
	{
		vic_irq_register(VIC_EXT_C, extab_int_isr);
		vic_irq_enable(VIC_EXT_C);
	}
}

void extab_int_clr(INT8U ext_src)
{
	EXTERNAL_INT_SFR	*pExternal_INT_Reg;

	pExternal_INT_Reg = get_EXTERNAL_INT_Reg_Base();

	if(ext_src == EXTA)
	{
		pExternal_INT_Reg->EXTERNAL_INT_KECON |= EXTA_INT;
	}
	else
	if(ext_src == EXTB)
	{
		pExternal_INT_Reg->EXTERNAL_INT_KECON |= EXTB_INT;
	}
	else
	{
		pExternal_INT_Reg->EXTERNAL_INT_KECON |= EXTC_INT;
	}
}

void extab_edge_set(INT8U ext_src, INT8U edge_type)
{
	EXTERNAL_INT_SFR	*pExternal_INT_Reg;

	pExternal_INT_Reg = get_EXTERNAL_INT_Reg_Base();

	if(ext_src == EXTA)
	{
		pExternal_INT_Reg->EXTERNAL_INT_KECON &= ~EXTA_POL;
		pExternal_INT_Reg->EXTERNAL_INT_KECON |= (edge_type << 3);
	}
	else
	if(ext_src == EXTB)
	{
		pExternal_INT_Reg->EXTERNAL_INT_KECON &= ~EXTB_POL;
		pExternal_INT_Reg->EXTERNAL_INT_KECON |= (edge_type << 4);
	}
	else
	{
		pExternal_INT_Reg->EXTERNAL_INT_KECON &= ~EXTC_POL;
		pExternal_INT_Reg->EXTERNAL_INT_KECON |= (edge_type << 5);
	}
}

void extab_enable_set(INT8U ext_src, BOOLEAN status)
{
	EXTERNAL_INT_SFR	*pExternal_INT_Reg;

	pExternal_INT_Reg = get_EXTERNAL_INT_Reg_Base();

	if(ext_src == EXTA)
	{
		if(status == TRUE)
		{
			pExternal_INT_Reg->EXTERNAL_INT_KECON |= EXTA_IEN;
		}
		else
		{
			pExternal_INT_Reg->EXTERNAL_INT_KECON &= ~EXTA_IEN;
		}
	}
	else
	if(ext_src == EXTB)
	{
		if(status == TRUE)
		{
			pExternal_INT_Reg->EXTERNAL_INT_KECON |= EXTB_IEN;
		}
		else
		{
			pExternal_INT_Reg->EXTERNAL_INT_KECON &= ~EXTB_IEN;
		}
	}
	else
	{
		if(status == TRUE)
		{
			pExternal_INT_Reg->EXTERNAL_INT_KECON |= EXTC_IEN;
		}
		else
		{
			pExternal_INT_Reg->EXTERNAL_INT_KECON &= ~EXTC_IEN;
		}
	}
}

void extab_user_isr_set(INT8U ext_src, void (*user_isr) (void))
{
	if(user_isr == 0)
	{
		return;
	}

	if(ext_src == EXTA)
	{
		exta_callback = user_isr;
	}
	else
	if(ext_src == EXTB)
	{
		extb_callback = user_isr;
	}
	else
	{
		extc_callback = user_isr;
	}
}

void extab_user_isr_clr(INT8U ext_src)
{
	if(ext_src == EXTA)
	{
		exta_callback = 0;
	}
	else
	if(ext_src == EXTB)
	{
		extb_callback = 0;
	}
	else
	{
		extc_callback = 0;
	}
}

void extab_int_isr(void)
{
	INT32U				status;
	EXTERNAL_INT_SFR	*pExternal_INT_Reg;

	pExternal_INT_Reg = get_EXTERNAL_INT_Reg_Base();

	status = pExternal_INT_Reg->EXTERNAL_INT_KECON;

	if(status & EXTA_INT)
	{
		pExternal_INT_Reg->EXTERNAL_INT_KECON |= EXTA_INT;
		if(exta_callback != 0)
		{
			(*exta_callback) ();
		}
	}

	if(status & EXTB_INT)
	{
		pExternal_INT_Reg->EXTERNAL_INT_KECON |= EXTB_INT;
		if(extb_callback != 0)
		{
			(*extb_callback) ();
		}
	}

	if(status & EXTC_INT)
	{
		pExternal_INT_Reg->EXTERNAL_INT_KECON |= EXTC_INT;
		if(extc_callback != 0)
		{
			(*extc_callback) ();
		}
	}
}

void drv_l1_key_change_int_init(void)
{
	
	//disable key change function
	R_SYSTEM_CLK_CTRL &=~(1<<9);			// Key Change Function Disable
		
	//disable all pin pos
	drv_l1_key_change_int_pin_pos_set(ALL_KEY_CHANGE_PIN,FALSE);
	
	//disable all key change pin interrput
	drv_l1_key_change_int_enable(ALL_KEY_CHANGE_PIN,FALSE);

	//enable key change function
	R_SYSTEM_CLK_CTRL |=(1<<9);			// Key Change Function Enable
	
}


void drv_l1_key_change_set_isr(void (*user_isr)(void))
{

	if(user_isr == 0)
	{
		return;
	}

		vic_irq_register(VIC_KEY_CHANGE, user_isr);		
		vic_irq_enable(VIC_KEY_CHANGE);	
}



void drv_l1_key_change_int_pin_pos_set(INT8U pin_pos,INT8U enable)
{

	INT8U status =0x00;
	
			//key change 0 
			if(pin_pos & KEY_CHANGE_PIN0)
			{
				if(enable == TRUE)
					{
						status|=(1<<0);
					}
				else
					{
						status&=~(1<<0);
					}				
			}

			//key change 1 
			if(pin_pos & KEY_CHANGE_PIN1)
			{
				if(enable == TRUE)
					{
						status|=(1<<1);
					}
				else
					{
						status&=~(1<<1);
					}					
			}


			//key change 2 	
			if(pin_pos & KEY_CHANGE_PIN2)
			{

				if(enable == TRUE)
					{
						status|=(1<<2);
					}
				else
					{
						status&=~(1<<2);
					}					
			}

			//key change 3 
			if(pin_pos & KEY_CHANGE_PIN3)
			{

				if(enable == TRUE)
					{
						status|=(1<<3);
					}
				else
					{
						status&=~(1<<3);
					}					
			}

			//key change 4 	
			if(pin_pos & KEY_CHANGE_PIN4)
			{

				if(enable == TRUE)
					{
						status|=(1<<4);
					}
				else
					{
						status&=~(1<<4);
					}					
			}


			//key change 5 	
			if(pin_pos & KEY_CHANGE_PIN5)
			{

				if(enable == TRUE)
					{
						status|=(1<<5);
					}
				else
					{
						status&=~(1<<5);
					}				
			}

			//key change 6
			if(pin_pos & KEY_CHANGE_PIN6)
			{

				if(enable == TRUE)
					{
						status|=(1<<6);
					}
				else
					{
						status&=~(1<<6);
					}				
			}

			//key change 7 
			if(pin_pos & KEY_CHANGE_PIN7)
			{

				if(enable == TRUE)
					{
						status|=(1<<7);
					}
				else
					{
						status&=~(1<<7);
					}
			}

			R_KEY_POS_EN =status;
}


void drv_l1_key_change_int_enable(INT8U pin_pos,INT8U enable)
{


			//key change 0 
			if(pin_pos & KEY_CHANGE_PIN0)
			{
				if(enable == TRUE)
					{
						R_INT_KEYCH|=(1<<0);
					}
				else
					{
						R_INT_KEYCH&=~(1<<0);
					}				
			}

			//key change 1 
			if(pin_pos & KEY_CHANGE_PIN1)
			{
				if(enable == TRUE)
					{
						R_INT_KEYCH|=(1<<2);
					}
				else
					{
						R_INT_KEYCH&=~(1<<2);
					}					
			}


			//key change 2 	
			if(pin_pos & KEY_CHANGE_PIN2)
			{

				if(enable == TRUE)
					{
						R_INT_KEYCH|=(1<<4);
					}
				else
					{
						R_INT_KEYCH&=~(1<<4);
					}					
			}

			//key change 3 
			if(pin_pos & KEY_CHANGE_PIN3)
			{

				if(enable == TRUE)
					{
						R_INT_KEYCH|=(1<<6);
					}
				else
					{
						R_INT_KEYCH&=~(1<<6);
					}					
			}

			//key change 4 	
			if(pin_pos & KEY_CHANGE_PIN4)
			{

				if(enable == TRUE)
					{
						R_INT_KEYCH|=(1<<8);
					}
				else
					{
						R_INT_KEYCH&=~(1<<8);
					}					
			}


			//key change 5 	
			if(pin_pos & KEY_CHANGE_PIN5)
			{

				if(enable == TRUE)
					{
						R_INT_KEYCH|=(1<<10);
					}
				else
					{
						R_INT_KEYCH&=~(1<<10);
					}				
			}

			//key change 6
			if(pin_pos & KEY_CHANGE_PIN6)
			{

				if(enable == TRUE)
					{
						R_INT_KEYCH|=(1<<12);
					}
				else
					{
						R_INT_KEYCH&=~(1<<12);
					}				
			}

			//key change 7 
			if(pin_pos & KEY_CHANGE_PIN7)
			{

				if(enable == TRUE)
					{
						R_INT_KEYCH|=(1<<14);
					}
				else
					{
						R_INT_KEYCH&=~(1<<14);
					}
			}


}


// Reading KEYCH, it will latch Key Value. Let the level reference.
void drv_l1_latch_level(void)
{
	INT32U latch_value;
	
	latch_value = R_KEYCH;
	
}
//=== This is for code configuration DON'T REMOVE or MODIFY it ===//
#endif //(defined _DRV_L1_EXT_INT) && (_DRV_L1_EXT_INT == 1)      //

//================================================================//
